package com.atguigu.gmall.activity.service.impl;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.activity.util.CacheHelper;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.MD5;
import com.atguigu.gmall.constant.MqConst;
import com.atguigu.gmall.model.activity.OrderRecode;
import com.atguigu.gmall.model.activity.SeckillGoods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

@Service
@SuppressWarnings("all")
public class SeckillGoodsServiceImpl implements SeckillGoodsService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 查询秒杀商品列表
     * @return
     */
    @Override
    public List<SeckillGoods> findAll() {
        List<SeckillGoods> SeckillGoodsList = redisTemplate.opsForHash().values(RedisConst.SECKILL_GOODS);
        return SeckillGoodsList;
    }

    /**
     * 查询秒杀状态
     * @param skuId
     * @param userId
     * @return
     */
    @Override
    public Result checkOrder(Long skuId, String userId) {
        // 用户在缓存中存在，有机会秒杀到商品
        boolean isExist =redisTemplate.hasKey(RedisConst.SECKILL_USER + userId);
        if (isExist) {
            //判断用户是否正在排队
            //判断用户是否下单
            boolean isHasKey = redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).hasKey(userId);
            if (isHasKey) {
                //抢单成功
                OrderRecode orderRecode = (OrderRecode) redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).get(userId);
                // 秒杀成功！
                return Result.build(orderRecode, ResultCodeEnum.SECKILL_SUCCESS);
            }
        }
        //判断是否下单
        boolean isExistOrder = redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS_USERS).hasKey(userId);
        if(isExistOrder) {
            String orderId = (String)redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS_USERS).get(userId);
            return Result.build(orderId, ResultCodeEnum.SECKILL_ORDER_SUCCESS);
        }
        String state = (String) CacheHelper.get(skuId.toString());
        if("0".equals(state)) {
            //已售罄 抢单失败
            return Result.build(null, ResultCodeEnum.SECKILL_FAIL);
        }
        //正在排队中
        return Result.build(null, ResultCodeEnum.SECKILL_RUN);
    }


    /**
     * 抢单
     * @param userId
     * @param skuId
     */
    @Override
    public void seckillOrder(String userId, Long skuId) {
        //校验状态位 切记，要从本地缓存里面取状态
        String status = (String) CacheHelper.get(skuId.toString());
        if ("0".equals(status)){
            return;
        }
        //校验是否下过单 setnx
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(RedisConst.SECKILL_USER+userId, skuId,RedisConst.SECKILL__TIMEOUT, TimeUnit.SECONDS);
        if (!flag){
            return;
        }
        //校验库存 从redis中检验
        String stockSkuId = (String) redisTemplate.boundListOps(RedisConst.SECKILL_STOCK_PREFIX + skuId).rightPop();
        if (StringUtils.isEmpty(stockSkuId)){
            //无库存，发布订阅，告诉集群当中其他的redis
           redisTemplate.convertAndSend("seckillpush",skuId+":0");
           return;
    }
        //生成订单信息存储到redis
        //封装订单信息对象
        OrderRecode orderRecode = new OrderRecode();
        orderRecode.setUserId(userId);
        orderRecode.setSeckillGoods(this.getSeckillGoods(skuId));
        orderRecode.setNum(1);
        orderRecode.setOrderStr(MD5.encrypt(userId+skuId));
        redisTemplate.boundHashOps(RedisConst.SECKILL_ORDERS).put(userId,orderRecode);
        //更新库存量
        this.updateStockCount(skuId);

    }

    private void updateStockCount(Long skuId) {
        //获得锁
        ReentrantLock lock = new ReentrantLock();
        lock.lock();
        try {
            //获取库存
            Long stockKey = redisTemplate.boundListOps(RedisConst.SECKILL_STOCK_PREFIX+skuId).size();
            //更新数据库信息
            SeckillGoods seckillGoods = this.getSeckillGoods(skuId);
            seckillGoods.setStockCount(stockKey.intValue());
            seckillGoodsMapper.updateById(seckillGoods);
            //更新缓存信息
            redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).put(skuId.toString(),seckillGoods);
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
    }
    /**
     * 获取秒杀商品信息
     * @param skuId
     * @return
     */
    @Override
    public SeckillGoods getSeckillGoods(Long skuId) {
        return (SeckillGoods) redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).get(skuId.toString());
    }
}
